package testplan.services.mock;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

import com.google.common.base.Predicate;
import com.google.inject.Singleton;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Collections2.filter;

import com.google.inject.internal.Nullable;
import testplan.entities.Project;
import testplan.entities.Release;
import testplan.services.ProjectService;
import testplan.services.mock.MockUserService;

@Singleton
public class MockProjectService implements ProjectService 
{
	protected ArrayList<Project> projectStore = new ArrayList<Project>();
    protected ArrayList<Release> releaseStore = new ArrayList<Release>();

    protected long projectKey = 0;
    protected long releaseKey = 0;
	
	public MockProjectService()
	{
        for(int i = 1; i < 4; i++)
        {
            createProject("Project " + i, MockUserService.DEV_AGENCY_ID, "Project description");
        }
        
        for (Project p : projectStore)
        {
            createRelease("1.0-SNAPSHOT", p.getKey());
            createRelease("0.9", p.getKey());
            createRelease("1.0-beta", p.getKey());
        }
	}

	@Override
	public void createProject(String name, long agencyId, String description) 
	{
		checkNotNull(name);
		checkNotNull(description);
		Project project = new Project(name, agencyId, description);
		projectStore.add(project);
		project.setKey(projectKey++);

        createRelease("name_me", project.getKey());
	}

	@Override
	public void deleteProject(final long projectId)
	{
        Project deleteProject = filter( projectStore, new Predicate<Project>() {
            @Override
            public boolean apply(@Nullable Project project)
            {
                return project.getKey() == projectId;
            }
        }).iterator().next();
		
		projectStore.remove(deleteProject);
	}

    public Set<Release> getReleases(final long projectId)
    {
        return new HashSet<Release>(filter(releaseStore, new Predicate<Release>() {
            @Override
            public boolean apply(@Nullable Release release)
            {
                return release.getProject() == projectId;
            }
        }));
    }

    @Override
    public void createRelease(String releaseName, long projectId)
    {
        checkNotNull(releaseName);
        checkNotNull(findByKey(projectId));
        Release r = new Release(releaseName, projectId, Release.Status.NEW);
        releaseStore.add(r);
        r.setKey(releaseKey++);
    }

    @Override
    public void updateRelease(long releaseId, String releaseName)
    {
        Release release = findReleaseByKey(releaseId);
        checkNotNull(releaseName);
        checkNotNull(release);
        release.setName(releaseName);
    }

    @Override
    public void updateRelease(long releaseId, Release.Status status)
    {
        Release release = findReleaseByKey(releaseId);
        checkNotNull(status);
        checkNotNull(release);
        release.setStatus(status);
    }

    @Override
	public Set<Project> findByAgency(final long agencyId)
	{
        return new HashSet<Project>(filter(projectStore, new Predicate<Project>(){
            @Override
            public boolean apply(@Nullable Project project)
            {
                return project.getAgency() == agencyId;
            }
        }));
	}

    private Project findByKey(final long projectId)
    {
        return filter(projectStore, new Predicate<Project>() {
            @Override
            public boolean apply(@Nullable Project project)
            {
                return project.getKey() == projectId;
            }
        }).iterator().next();
    }

    private Release findReleaseByKey(final long releaseId)
    {
        return filter(releaseStore, new Predicate<Release>() {
            @Override
            public boolean apply(@Nullable Release release)
            {
                return release.getKey() == releaseId;
            }
        }).iterator().next();
    }

}
